package com.black.cat.jvm.classfile;

import com.black.cat.jvm.classfile.attribute.AttributeInfo;
import com.black.cat.jvm.classfile.attribute.BaseAttributeInfo;
import com.black.cat.jvm.classfile.attribute.CodeAttribute;
import com.black.cat.jvm.classfile.attribute.ConstantValueAttribute;
import com.black.cat.jvm.classfile.constantpool.ConstantPool;
import lombok.Data;

import java.util.Arrays;

/**
 * @Author blackcat
 * @create 2021/8/11 20:49
 * @version: 1.0
 * @description:字段表和方法表 field_info {
 * u2 access_flags;
 * u2 name_index;
 * u2 descriptor_index;
 * u2 attributes_count;
 * attribute_info attributes[attributes_count];
 * }
 */
@Data
public class MemberInfo {

    private ConstantPool constantPool;

    private int accessFlags;
    private int nameIndex;
    private int descriptorIndex;
    private AttributeInfo[] attributes;

    public MemberInfo(ConstantPool constantPool, ClassReader reader) {
        this.constantPool = constantPool;
        accessFlags = reader.nextU2ToInt();
        nameIndex = reader.nextU2ToInt();
        descriptorIndex = reader.nextU2ToInt();
        attributes = BaseAttributeInfo.readAttributes(reader, constantPool);
    }

    public static MemberInfo[] readMembers(ConstantPool constantPool, ClassReader reader) {
        int fieldCount = reader.nextU2ToInt();
        MemberInfo[] fields = new MemberInfo[fieldCount];

        for (int i = 0; i < fieldCount; i++) {
            fields[i] = new MemberInfo(constantPool, reader);
        }

        return fields;
    }

    public CodeAttribute codeAttribute() {
        for (AttributeInfo attrInfo : attributes) {
            if (attrInfo instanceof CodeAttribute) return (CodeAttribute) attrInfo;
        }
        return null;
    }

    public ConstantValueAttribute ConstantValueAttribute() {
        for (AttributeInfo attrInfo : attributes) {
            if (attrInfo instanceof ConstantValueAttribute) return (ConstantValueAttribute) attrInfo;
        }
        return null;
    }

    public String name() {
        return this.constantPool.getUtfStringByIndex(this.nameIndex);
    }

    public String descriptor() {
        return this.constantPool.getUtfStringByIndex(this.descriptorIndex);
    }

    @Override
    public String toString() {
        return "MemberInfo{" +
                "accessFlags=" + accessFlags +
                ", nameIndex=" + nameIndex +
                ", descriptorIndex=" + descriptorIndex +
                ", attributes=" + Arrays.toString(attributes) +
                "}\n";
    }
}
